﻿using System;
using System.Threading.Tasks;
using System.Threading.Channels;


/*
 * Fun 方法演示了创建一个无界通道（Channel.CreateUnbounded<Message>），
 * 并启动两个消息发送者任务和一个消息接收者任务。
 *
 * 发送者任务将消息写入通道，而接收者任务从通道读取消息。
 * 管道通过 ChannelWriter 和 ChannelReader 实现异步数据流动，
 * 允许发送者和接收者在不同的线程中并发运行，实现异步通信。
 * 最终，调用 channel.Writer.Complete() 以标记通道写入完成，
 * 接收者任务完成后，整个过程结束。
 */
namespace Demo
{
    /// <summary>
    /// 表示一条消息的类
    /// </summary>
    public class Message
    {
        // 消息类的构造函数，接收发件人ID和消息内容
        public Message(int FromId, string Content) { }

        // 消息内容属性
        public string Content { get; internal set; }
        // 发件人ID属性
        public int FromId { get; internal set; }
    }

    /// <summary>
    /// 用于演示异步通信的类
    /// </summary>
    public class ChannelDemo
    {
        // 异步方法，演示消息的发送和接收
        public async void Fun()
        {
            // 创建一个无界的通道
            var channel = Channel.CreateUnbounded<Message>();

            // 创建两个发送者任务和一个接收者任务
            var sender1 = SendMessageAsync(channel.Writer, 1);
            var sender2 = SendMessageAsync(channel.Writer, 2);
            var receiver = ReceiveMessageAsync(channel.Reader, 3);

            // 等待所有发送者任务完成
            await Task.WhenAll(sender1, sender2);
            // 标记通道写入完成
            channel.Writer.Complete();
            // 等待接收者任务完成
            await receiver;
        }

        /// <summary>
        /// 异步发送消息的方法
        /// </summary>
        /// <param name="write"></param>
        /// <param name="id"></param>
        async Task SendMessageAsync(ChannelWriter<Message> write, int id)
        {
            for (int i = 0; i <= 20; i++)
            {
                // 将消息写入通道
                await write.WriteAsync(new Message(id, i.ToString()));

                // 打印发送信息
                Console.WriteLine($"Thread {id} sent {i}");

                // 等待100毫秒
                await Task.Delay(100);
            }
        }

        /// <summary>
        /// 异步接收消息的方法
        /// </summary>
        /// <param name="reader"></param>
        /// <param name="id"></param>
        async Task ReceiveMessageAsync(ChannelReader<Message> reader, int id)
        {
            try
            {
                // 循环读取消息直到通道完成
                while (!reader.Completion.IsCompleted)
                {
                    var message = await reader.ReadAsync();
                    // 打印接收的信息
                    Console.WriteLine($"Thread {id} received {message.Content} from {message.FromId}");
                }
            }
            catch (ChannelClosedException)
            {
                // 捕获并打印通道关闭异常
                Console.WriteLine($"Thread {id} Channel Closed");
            }
        }
    }
}

